/*
Copyright 2000-2011 Francois de Bertrand de Beuvron

This file is part of CoursBeuvron.

CoursBeuvron is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

CoursBeuvron is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with CoursBeuvron.  If not, see <http://www.gnu.org/licenses/>.
 */
package fr.insa.beuvron.tps.m2.dessin2DV2;

public class Segment implements Figure {

    private Point p1;
    private Point p2;

    public Segment() {
    }

    public Segment(Point p1, Point p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    public static Segment cree(Point p1, Point p2) {
        return new Segment(p1, p2);
    }

    public static Segment demande() {
        System.out.println("entrez le point du début du segment : ");
        Point p1 = Point.demande();
        System.out.println("entrez le point de fin du segment : ");
        Point p2 = Point.demande();
        return Segment.cree(p1, p2);
    }

    public Point getP1() {
        return p1;
    }

    public void setP1(Point val) {
        this.p1 = val;
    }

    public Point getP2() {
        return p2;
    }

    public void setP2(Point val) {
        this.p2 = val;
    }

    @Override
    public double maxX() {
        return Math.max(this.p1.maxX(), this.p2.maxX());
    }

    @Override
    public double minX() {
        return Math.min(this.p1.minX(), this.p2.minX());
    }

    @Override
    public double maxY() {
        return Math.max(this.p1.maxY(), this.p2.maxY());
    }

    @Override
    public double minY() {
        return Math.min(this.p1.minY(), this.p2.minY());
    }

    /**
     * Pour calculer la distance entre un segment [P1,P2] et un point P3 ; P1=(x1,y1), P2=(x2,y2), P3=(x3,y3) :
     * Tous les points P de la droite passant par P1 et P2 peuvent être définis par : P = P1 + u (P2-P1) ; u ∈ ℝ
     * On peut calculer up, la valeur de u pour la projection P4=(x4,y4) de P3 sur la droite (P1,P2) :
     * up = ((x3-x1)(x2-x1) + (y3-y1)(y2-y1) / ((x2-x1)^2+(y2-y1)^2)
     * @param p un point
     * @return distance entre ce segment et le point
     */
    @Override
    public double distance(Point p) {
        if (this.p1.egal(this.p2)) {
            // cas particulier d'un segment de taille nulle
            return this.p1.distance(p);
        } else {
            double x1 = this.p1.getAbscisse();
            double y1 = this.p1.getOrdonnee();
            double x2 = this.p2.getAbscisse();
            double y2 = this.p2.getOrdonnee();
            double dx = x2 - x1;
            double dy = y2 - y1;
            double x3 = p.getAbscisse();
            double y3 = p.getOrdonnee();
            double up = ((x3 - x1) * dx + (y3 - y1) * dy) / (dx * dx + dy * dy);
            if (up < 0) {
                return this.p1.distance(p);
            } else if (up > 1) {
                return this.p2.distance(p);
            } else {
                Point p4 = new Point(x1 + up * dx, y1 + up * dy);
                return p4.distance(p);
            }
        }
    }

    @Override
    public String toString() {
        return "[" + this.p1 + " , " + this.p2 + "]";
    }
       
    @Override
    public String jolieDescription(int niveau) {
        return Utils.indent("Segment " + this.toString(), niveau*2);
    }
}
